{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "impressed-corporation",
   "metadata": {},
   "outputs": [],
   "source": [
    "#https://www.backtrader.com/docu/\n",
    "\n",
    "#先引入后面可能用到的包（package）\n",
    "import pandas as pd  \n",
    "from datetime import datetime\n",
    "import backtrader as bt\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline  \n",
    "\n",
    "#正常显示画图时出现的中文和负号\n",
    "from pylab import mpl\n",
    "mpl.rcParams['font.sans-serif']=['SimHei']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "modified-cabin",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.doubanio.com/simple\n",
      "Collecting backtrader\n",
      "  Downloading https://pypi.doubanio.com/packages/1a/bf/78aadd993e2719d6764603465fde163ba6ec15cf0e81f13e39ca13451348/backtrader-1.9.76.123-py2.py3-none-any.whl (410 kB)\n",
      "\u001b[K     |████████████████████████████████| 410 kB 2.5 MB/s eta 0:00:01\n",
      "\u001b[?25hInstalling collected packages: backtrader\n",
      "Successfully installed backtrader-1.9.76.123\n",
      "\u001b[33mWARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv\u001b[0m\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "# pip install backtrader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "green-savage",
   "metadata": {},
   "outputs": [],
   "source": [
    "class my_strategy1(bt.Strategy):\n",
    "    #全局设定交易策略的参数\n",
    "    params=(\n",
    "        ('maperiod',20),\n",
    "           )\n",
    "\n",
    "    def __init__(self):\n",
    "        #指定价格序列\n",
    "        self.dataclose=self.datas[0].close\n",
    "        # 初始化交易指令、买卖价格和手续费\n",
    "        self.order = None\n",
    "        self.buyprice = None\n",
    "        self.buycomm = None\n",
    "\n",
    "        #添加移动均线指标，内置了talib模块\n",
    "        self.sma = bt.indicators.SimpleMovingAverage(\n",
    "                      self.datas[0], period=self.params.maperiod)\n",
    "    def next(self):\n",
    "        if self.order: # 检查是否有指令等待执行, \n",
    "            return\n",
    "        # 检查是否持仓   \n",
    "        if not self.position: # 没有持仓\n",
    "            #执行买入条件判断：收盘价格上涨突破20日均线\n",
    "            if self.dataclose[0] > self.sma[0]:\n",
    "                #执行买入\n",
    "                self.order = self.buy(size=500)         \n",
    "        else:\n",
    "            #执行卖出条件判断：收盘价格跌破20日均线\n",
    "            if self.dataclose[0] < self.sma[0]:\n",
    "                #执行卖出\n",
    "                self.order = self.sell(size=500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "smart-finding",
   "metadata": {},
   "outputs": [],
   "source": [
    "mpl.rcParams['axes.unicode_minus']=False\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "working-woman",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "本接口即将停止更新，请尽快使用Pro版接口：https://waditu.com/document/2\n"
     ]
    }
   ],
   "source": [
    " #使用tushare旧版接口获取数据\n",
    "import tushare as ts \n",
    "def get_data(code,start='2010-01-01',end='2020-03-31'):\n",
    "    df=ts.get_k_data(code,autype='qfq',start=start,end=end)\n",
    "    df.index=pd.to_datetime(df.date)\n",
    "    df['openinterest']=0\n",
    "    df=df[['open','high','low','close','volume','openinterest']]\n",
    "    return df\n",
    "dataframe=get_data('600000')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "swedish-flavor",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>close</th>\n",
       "      <th>volume</th>\n",
       "      <th>openinterest</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2010-01-04</th>\n",
       "      <td>6.835</td>\n",
       "      <td>6.847</td>\n",
       "      <td>6.625</td>\n",
       "      <td>6.634</td>\n",
       "      <td>661913.38</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-05</th>\n",
       "      <td>6.703</td>\n",
       "      <td>6.756</td>\n",
       "      <td>6.509</td>\n",
       "      <td>6.684</td>\n",
       "      <td>1151479.43</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-06</th>\n",
       "      <td>6.666</td>\n",
       "      <td>6.669</td>\n",
       "      <td>6.537</td>\n",
       "      <td>6.553</td>\n",
       "      <td>967825.75</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-07</th>\n",
       "      <td>6.537</td>\n",
       "      <td>6.587</td>\n",
       "      <td>6.356</td>\n",
       "      <td>6.406</td>\n",
       "      <td>852360.72</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2010-01-08</th>\n",
       "      <td>6.368</td>\n",
       "      <td>6.512</td>\n",
       "      <td>6.356</td>\n",
       "      <td>6.478</td>\n",
       "      <td>657076.46</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2020-03-25</th>\n",
       "      <td>10.200</td>\n",
       "      <td>10.270</td>\n",
       "      <td>10.120</td>\n",
       "      <td>10.150</td>\n",
       "      <td>321723.00</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2020-03-26</th>\n",
       "      <td>10.100</td>\n",
       "      <td>10.370</td>\n",
       "      <td>10.080</td>\n",
       "      <td>10.230</td>\n",
       "      <td>309218.00</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2020-03-27</th>\n",
       "      <td>10.350</td>\n",
       "      <td>10.380</td>\n",
       "      <td>10.200</td>\n",
       "      <td>10.240</td>\n",
       "      <td>271080.00</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2020-03-30</th>\n",
       "      <td>10.180</td>\n",
       "      <td>10.280</td>\n",
       "      <td>10.110</td>\n",
       "      <td>10.280</td>\n",
       "      <td>260460.00</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2020-03-31</th>\n",
       "      <td>10.300</td>\n",
       "      <td>10.360</td>\n",
       "      <td>10.130</td>\n",
       "      <td>10.150</td>\n",
       "      <td>261449.00</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2442 rows × 6 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "              open    high     low   close      volume  openinterest\n",
       "date                                                                \n",
       "2010-01-04   6.835   6.847   6.625   6.634   661913.38             0\n",
       "2010-01-05   6.703   6.756   6.509   6.684  1151479.43             0\n",
       "2010-01-06   6.666   6.669   6.537   6.553   967825.75             0\n",
       "2010-01-07   6.537   6.587   6.356   6.406   852360.72             0\n",
       "2010-01-08   6.368   6.512   6.356   6.478   657076.46             0\n",
       "...            ...     ...     ...     ...         ...           ...\n",
       "2020-03-25  10.200  10.270  10.120  10.150   321723.00             0\n",
       "2020-03-26  10.100  10.370  10.080  10.230   309218.00             0\n",
       "2020-03-27  10.350  10.380  10.200  10.240   271080.00             0\n",
       "2020-03-30  10.180  10.280  10.110  10.280   260460.00             0\n",
       "2020-03-31  10.300  10.360  10.130  10.150   261449.00             0\n",
       "\n",
       "[2442 rows x 6 columns]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataframe"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "destroyed-intensity",
   "metadata": {},
   "outputs": [],
   "source": [
    "#回测期间\n",
    "start=datetime(2010, 3, 31)\n",
    "end=datetime(2020, 3, 31)\n",
    "# 加载数据\n",
    "data = bt.feeds.PandasData(dataname=dataframe,fromdate=start,todate=end)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "minute-electron",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 初始化cerebro回测系统设置                           \n",
    "cerebro = bt.Cerebro()  \n",
    "#将数据传入回测系统\n",
    "cerebro.adddata(data) \n",
    "# 将交易策略加载到回测系统中\n",
    "cerebro.addstrategy(my_strategy1) \n",
    "# 设置初始资本为10,000\n",
    "startcash = 10000\n",
    "cerebro.broker.setcash(startcash) \n",
    "# 设置交易手续费为 0.2%\n",
    "cerebro.broker.setcommission(commission=0.002) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "desperate-hazard",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "初始资金: 10000\n",
      "回测期间：20100331:20200331\n",
      "总资金: 12000.36\n",
      "净收益: 2000.36\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "d1=start.strftime('%Y%m%d')\n",
    "d2=end.strftime('%Y%m%d')\n",
    "print(f'初始资金: {startcash}\\n回测期间：{d1}:{d2}')\n",
    "#运行回测系统\n",
    "cerebro.run()\n",
    "#获取回测结束后的总资金\n",
    "portvalue = cerebro.broker.getvalue()\n",
    "pnl = portvalue - startcash\n",
    "#打印结果\n",
    "print(f'总资金: {round(portvalue,2)}')\n",
    "'''\n",
    "\n",
    "初始资金: 10000\n",
    "回测期间：20100331:20200331\n",
    "总资金: 12065.36\n",
    "净收益: 2065.36\n",
    "'''\n",
    "print(f'净收益: {round(pnl,2)}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "generous-small",
   "metadata": {},
   "outputs": [
    {
     "ename": "ImportError",
     "evalue": "cannot import name 'warnings' from 'matplotlib.dates' (/root/.pyenv/versions/3.7.0/lib/python3.7/site-packages/matplotlib/dates.py)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mImportError\u001b[0m                               Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-12-7a9b9a7f99a1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# %matplotlib inline #在jupyter notebook上运行\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mcerebro\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstyle\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'candlestick'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m~/.pyenv/versions/3.7.0/lib/python3.7/site-packages/backtrader/cerebro.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(self, plotter, numfigs, iplot, start, end, width, height, dpi, tight, use, **kwargs)\u001b[0m\n\u001b[1;32m    972\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    973\u001b[0m         \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mplotter\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 974\u001b[0;31m             \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mplot\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    975\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moldsync\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    976\u001b[0m                 \u001b[0mplotter\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mplot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mPlot_OldSync\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.pyenv/versions/3.7.0/lib/python3.7/site-packages/backtrader/plot/__init__.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     40\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     41\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 42\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPlot\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mPlot_OldSync\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     43\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mscheme\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPlotScheme\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.pyenv/versions/3.7.0/lib/python3.7/site-packages/backtrader/plot/plot.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     42\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mfinance\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mplot_candlestick\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mplot_ohlc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mplot_volume\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mplot_lineonclose\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     43\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mformatters\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mMyVolFormatter\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mMyDateFormatter\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mgetlocator\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 44\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mlocator\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mloc\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     45\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mmulticursor\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mMultiCursor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     46\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mscheme\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mPlotScheme\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m~/.pyenv/versions/3.7.0/lib/python3.7/site-packages/backtrader/plot/locator.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m     33\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mmatplotlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdates\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mAutoDateFormatter\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mADFormatter\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     34\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 35\u001b[0;31m from matplotlib.dates import (HOURS_PER_DAY, MIN_PER_HOUR, SEC_PER_MIN,\n\u001b[0m\u001b[1;32m     36\u001b[0m                               \u001b[0mMONTHS_PER_YEAR\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mDAYS_PER_WEEK\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     37\u001b[0m                               \u001b[0mSEC_PER_HOUR\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mSEC_PER_DAY\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mImportError\u001b[0m: cannot import name 'warnings' from 'matplotlib.dates' (/root/.pyenv/versions/3.7.0/lib/python3.7/site-packages/matplotlib/dates.py)"
     ]
    }
   ],
   "source": [
    "# %matplotlib inline #在jupyter notebook上运行\n",
    "cerebro.plot(style='candlestick')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "static-bridge",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
